package com.brainhealth.common.utils.http;

import org.apache.commons.io.IOUtils;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream;

public class HttpClientUtil {

    public  static String doGet(String url, Map<String, String> param, String header) {
        // 创建Httpclient对象
        CloseableHttpClient httpclient = HttpClients.createDefault();
        String resultString = "";
        CloseableHttpResponse response = null;
        try {
            // 创建uri
            URIBuilder builder = new URIBuilder(url);
            if (param != null) {
                for (String key : param.keySet()) {
                    builder.addParameter(key, param.get(key));
                }
            }
            URI uri = builder.build();
            // 创建http GET请求
            HttpGet httpGet = new HttpGet(uri);
            if (header != null || header != "")
            {
                httpGet.addHeader("Authorization",header);
            }
            // 执行请求
            response = httpclient.execute(httpGet);
            // 判断返回状态是否为200
            if (response.getStatusLine().getStatusCode() == 200) {
                resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (response != null) {
                    response.close();
                }
                httpclient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return resultString;
    }

    public static String doGetInfo(String url, Map<String, String> param) {
        // 创建Httpclient对象
        CloseableHttpClient httpclient = HttpClients.createDefault();
        String resultString = "";
        CloseableHttpResponse response = null;
        try {
            // 创建uri
            URIBuilder builder = new URIBuilder(url);
            if (param != null) {
                for (String key : param.keySet()) {
                    builder.addParameter(key, param.get(key));
                }
            }
            URI uri = builder.build();
            // 创建http GET请求
            HttpGet httpGet = new HttpGet(uri);
            // 执行请求
            response = httpclient.execute(httpGet);
            // 判断返回状态是否为200
            if (response.getStatusLine().getStatusCode() == 200) {
                resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (response != null) {
                    response.close();
                }
                httpclient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return resultString;
    }

    public static String doGet(String url) {
        return doGet(url, null,"");
    }

    public static String doPost(String url, Map<String, String> param) {
        // 创建Httpclient对象
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = null;
        String resultString = "";
        try {
            // 创建Http Post请求
            HttpPost httpPost = new HttpPost(url);
            httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded");
            // 创建参数列表
            if (param != null) {
                List<NameValuePair> paramList = new ArrayList<>();
                for (String key : param.keySet()) {
                    paramList.add(new BasicNameValuePair(key, param.get(key)));
                }
                // 模拟表单
                UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList,"UTF-8");
                httpPost.setEntity(entity);
            }
            // 执行http请求
            response = httpClient.execute(httpPost);
            resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                response.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return resultString;
    }

    public static String doPost(String url) {
        return doPost(url, null);
    }

    public static String doPostJson(String url, String json) {
        return doPostJsonString(url,json,"");
    }

    public static String doPostJsonWithHeader(String url, String json,String header) {
        return doPostJsonString(url, json, header);
    }

    private static String doPostJsonString(String url, String json, String header)
    {
        // 创建Httpclient对象
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = null;
        String resultString = "";
        try {
            // 创建Http Post请求
            HttpPost httpPost = new HttpPost(url);
            if (Strings.isNotEmpty(header)) {
                httpPost.setHeader("Sign", header);
            }
            // 创建请求内容
            StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
            httpPost.setEntity(entity);
            // 执行http请求
            response = httpClient.execute(httpPost);
            resultString = EntityUtils.toString(response.getEntity(), "utf-8");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                response.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return resultString;
    }

    public static String doPostJsonWithHeaderMap(String url, String json, HashMap<String,String> mHeader)
    {
        // 创建Httpclient对象
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = null;
        String resultString = "";
        try {
            // 创建Http Post请求
            HttpPost httpPost = new HttpPost(url);
            for (Map.Entry<String,String> entry: mHeader.entrySet())
            {
                httpPost.setHeader(entry.getKey(), entry.getValue());
            }
            // 创建请求内容
            StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
            httpPost.setEntity(entity);
            // 执行http请求
            response = httpClient.execute(httpPost);
            resultString = EntityUtils.toString(response.getEntity(), "utf-8");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                response.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return resultString;
    }

    /**
     * 数据流post请求
     *888z
     * @param urlStr
     * @param strInfo
     */
    public static String doPostXmlStream(String urlStr, String strInfo) {
        String reStr = "";
        try {
            URL url = new URL(urlStr);
            URLConnection con = url.openConnection();
            con.setDoOutput(true);
            //con.setRequestProperty("Pragma:", "no-cache");
            con.setRequestProperty("Cache-Control", "no-cache");
            con.setRequestProperty("Content-Type", "text/xml");
            OutputStreamWriter out = new OutputStreamWriter(con.getOutputStream());
            out.write(new String(strInfo.getBytes("utf-8")));
            out.flush();
            out.close();
            BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), "utf-8"));
            String line = "";
            for (line = br.readLine(); line != null; line = br.readLine()) {
                reStr += line;
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return reStr;
    }

    /**
     * 匹配以("fieldName":")开头,以(")结尾的字符串，并且存储到分组中
     * 正则表达式匹配字段值
     * 不包含空值
     * (?<=(href=")) 表示 匹配以(href=")开头的字符串，并且捕获(存储)到分组中
     * (?=(">)) 表示 匹配以(">)结尾的字符串，并且捕获(存储)到分组中
     *
     * @param jsonStr
     * @param fieldName
     * @return
     */
    public static List getFieldListFromJsonStr(String jsonStr, String fieldName) {
        List fieldValues = new ArrayList<>();
        String regex = "(?<=(\"" + fieldName + "\":\")).*?(?=(\"))";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(jsonStr);
        while (matcher.find()) {
            if (Strings.isNotEmpty(matcher.group().trim())) {
                fieldValues.add(matcher.group().trim());
            }
        }
        return fieldValues;
    }

    /**
     * 使用post请求
     * @param obj  请求参数对象
     * @param httpUrl 请求URL地址
     * @return 请求网关的返回值
     * @throws Exception
     */
    public String executePost(Object obj, String httpUrl) throws Exception {

        String result = "";
        Class cls = obj.getClass();
        Field[] fields = cls.getDeclaredFields();
        List<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>();
        //设置请求参数
        String fieldName = null;
        String fieldNameUpper = null;
        Method getMethod = null;
        String value = null;
        for (int i = 0; i < fields.length; i++)   {//循环设置请求参数
            fieldName = fields[i].getName();
            fieldNameUpper = Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1);
            getMethod = cls.getMethod("get" + fieldNameUpper);//通过反射获取get方法
            value = (String) getMethod.invoke(obj);//通过反射调用get方法
            if(value != null) {//请求参数值不为空，才设置
                params.add(new BasicNameValuePair(fieldName, value));
            }
        }
        HttpPost httppost = new HttpPost(httpUrl);//设置HttpPost
        httppost.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8)); // 设置参数的编码UTF-8
        HttpClient httpclient = new DefaultHttpClient();//创建HttpClient
        HttpEntity entity = httpclient.execute(httppost).getEntity();//Http请求网关
        if(entity != null&& entity.getContentLength() >0) {//返回值不为空，且长度大于0
            result= EntityUtils.toString(entity);//将返回值转换成字符串
        }//处理返回结果
        httpclient.getConnectionManager().shutdown();//关闭连接
        return result;//返回返回值
    }

    /// <summary>
    /// 模拟http的get请求
    /// </summary>
    /// <param name="Url">请求地址</param>
    /// <param name="postDataStr">请求参数(前面不用加问号)</param>
    /// <returns></returns>
    public static String _HttpGet(String Url, String data) {
        OutputStream outPut = null;
        HttpURLConnection urlConnection = null;
        InputStream in = null;
        try {
            String dataString = Strings.isNotEmpty(data) ? "" : data;
            URL url = new URL(Url + dataString);
            urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setRequestMethod("GET");
            urlConnection.setDoOutput(true);
            urlConnection.setDoInput(true);
            urlConnection.setRequestProperty("Content-Type", "text/html; charset=UTF-8");
            urlConnection.setConnectTimeout(60 * 1000);
            urlConnection.setReadTimeout(60 * 1000);
            urlConnection.connect();
            // POST data

            outPut = urlConnection.getOutputStream();
            outPut.write(data.getBytes("UTF-8"));
            outPut.flush();

            // read response
            if (urlConnection.getResponseCode() < 400) {
                in = urlConnection.getInputStream();
            } else {
                in = urlConnection.getErrorStream();
            }

            List<String> lines = IOUtils.readLines(in, urlConnection.getContentEncoding());
            StringBuffer strBuf = new StringBuffer();
            for (String line : lines) {
                strBuf.append(line);
            }
            return strBuf.toString();
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        } finally {
            IOUtils.closeQuietly(outPut);
            IOUtils.closeQuietly(in);
            if (urlConnection != null) {
                urlConnection.disconnect();
            }
        }
    }

    public static String _PostUrlHtml(String strWebPath, byte[] byPost, String strContentType, boolean isSetGZip , String strOnlycode)
    {
        OutputStream outPut = null;
        HttpURLConnection urlConnection = null;
        InputStream in = null;
        try {
            URL url = new URL(strWebPath);
            urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setRequestMethod("POST");
            urlConnection.setDoOutput(true);
            urlConnection.setDoInput(true);
            urlConnection.setConnectTimeout(60 * 1000);
            urlConnection.setReadTimeout(60 * 1000);
            urlConnection.setRequestProperty("Content-Type",strContentType);
            urlConnection.setRequestProperty("ContentLength",String.valueOf(byPost.length));
            if (!Strings.isNotEmpty(strOnlycode)) {
                urlConnection.setRequestProperty("request-id", strOnlycode);
            }
            if (isSetGZip) {
                urlConnection.setRequestProperty("Accept-Encoding", "gzip,deflate,sdch");
            }

            urlConnection.connect();
            outPut = urlConnection.getOutputStream();
            outPut.write(byPost);
            outPut.flush();

            // read response
            if (urlConnection.getResponseCode() < 400) {
                in = urlConnection.getInputStream();
            } else {
                in = urlConnection.getErrorStream();
            }

            List<String> lines = IOUtils.readLines(in, urlConnection.getContentEncoding());
            StringBuffer strBuf = new StringBuffer();
            for (String line : lines) {
                strBuf.append(line);
            }
            return strBuf.toString();
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        } finally {
            IOUtils.closeQuietly(outPut);
            IOUtils.closeQuietly(in);
            if (urlConnection != null) {
                urlConnection.disconnect();
            }
        }
    }

    public static String getResult(String url, String accept, String token_type, String access_token, String contentType, String requestType, String parms, int nOutTime, boolean ContainAccessToken)
    {
        requestType = requestType.toLowerCase();
        String result = Strings.EMPTY;
        OutputStream outPut = null;
        HttpURLConnection urlConnection = null;
        InputStream in = null;
        try {
              URL webUrl = new URL(url);
            urlConnection = (HttpURLConnection) webUrl.openConnection();
            if (!Strings.isEmpty(accept)) {
                urlConnection.setRequestProperty("Accept", accept);
            }
            if (!Strings.isEmpty(contentType)) {
                urlConnection.setRequestProperty("Content-Type", contentType);
            }
            urlConnection.setDoOutput(true);
            urlConnection.setDoInput(true);
            urlConnection.setRequestMethod(requestType.toUpperCase());
            urlConnection.setConnectTimeout(nOutTime);
            urlConnection.setReadTimeout(nOutTime);
            if (!Strings.isEmpty(token_type) && !Strings.isEmpty(access_token))
            {
                urlConnection.setRequestProperty("Authorization", token_type + " " + access_token);
            }
            if (ContainAccessToken == true && !Strings.isEmpty(access_token))
            {
                urlConnection.setRequestProperty("Access-Token", access_token);
            }
            urlConnection.connect();
            if (requestType.equals("POST") || requestType.equals("post")) {
                outPut = urlConnection.getOutputStream();
                outPut.write(parms.getBytes("UTF-8"));
                outPut.flush();
            }
            if (urlConnection.getResponseCode() < 400) {
                in = urlConnection.getInputStream();
            } else {
                in = urlConnection.getErrorStream();
                System.out.println(in);
            }
            if (urlConnection.getContentEncoding()!=null && urlConnection.getContentEncoding().toLowerCase().equals("gzip")) {
                GZIPInputStream gzipInputStream = new GZIPInputStream(in);
                byte[] inBytes = IOUtils.toByteArray(gzipInputStream);
                return GZIPUtils.uncompressToString(inBytes, GZIPUtils.GZIP_ENCODE_UTF_8);
            }
            List<String> lines = IOUtils.readLines(in, urlConnection.getContentEncoding());
            StringBuffer strBuf = new StringBuffer();
            for (String line : lines) {
                strBuf.append(line);
            }
            return strBuf.toString();
        }catch (Exception e) {
            e.printStackTrace();
            return result;
        } finally {
            IOUtils.closeQuietly(outPut);
            IOUtils.closeQuietly(in);
            if (urlConnection != null) {
                urlConnection.disconnect();
            }
        }
    }

    /**
     * 下载网络文件
     * @param fileUrl 网络文件地址
     * @param downFilePath 本机文件路径
     * @throws MalformedURLException
     */
    public static void downloadNetworkFile(String fileUrl, String downFilePath) throws MalformedURLException {
        int bytesum = 0;
        int byteread = 0;
        URL url = new URL(fileUrl);
        try {
            URLConnection conn = url.openConnection();
            InputStream inStream = conn.getInputStream();
            FileOutputStream fs = new FileOutputStream(downFilePath);
            byte[] buffer = new byte[1204];
            while ((byteread = inStream.read(buffer)) != -1) {
                bytesum += byteread;
                fs.write(buffer, 0, byteread);
            }
            fs.flush();
            fs.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
